package socket.wtyt.com.wtytsocket;

import android.os.Looper;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by duantianhui on 2018/3/21.
 */

public class SocketClient {
    private static final Socket SOCKET = null;
    private static final DataInputStream dis = null;//输入
    private static final DataOutputStream dos = null;//输出
    private Timer heartBeatTimer;
    private TimerTask heartBeatTask;

    private SocketClient() {
    }

    private static SocketClient socketClient;
    private static DatagramSocket socketUdp = null;
    private static Socket socketTcp = null;
    private static SocketUtil socketUtil;

    //获取单例
    public static SocketClient getSingle() {
        if (socketClient == null) {
            synchronized (SocketClient.class) {//加锁 多个进程使用
                if (socketClient == null) {//优化
                    socketClient = new SocketClient();
                }
            }
        }
        return socketClient;
    }

    /**
     * 必须要调一次，该app特殊，客户端一旦断开socket，服务器一直死循环接收空包（服务器没人去改）
     * 所以客户端这边，一旦连接上之后，就不要断开
     * @param serverIp
     * @param serverPort
     */
    public void setServerIp(final String serverIp, final int serverPort) {
        try {
            if(socketTcp == null || !socketTcp.isConnected()) {
                socketTcp = new Socket(serverIp, serverPort);
                socketTcp.setKeepAlive(true);

                socketUtil = new SocketUtil(socketTcp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试链接
     */
    public void testConnect(final String serverIp, final int serverPort, final IConnectListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    setServerIp(serverIp, serverPort);
//                    Socket socketTcp = new Socket(serverIp, serverPort);
//                    socketTcp.setKeepAlive(false);
//
//                    final SocketUtil util = new SocketUtil(socketTcp);
                    final StringBuffer msg = new StringBuffer();
                    if(socketUtil.isConnect()) {
                        msg.append("连接成功");
                    }else {
                        msg.append("连接失败，请重试！");
                    }

                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            if(listener != null) {
                                listener.isConnect(socketUtil.isConnect(), msg.toString());
                            }
                        }
                    });
                    socketUtil.closeConnect();

                } catch (final Exception e) {
                    e.printStackTrace();
                    runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            if(listener != null) {
                                listener.isConnect(false, "连接发生异常：" + e.getMessage());
                            }
                        }
                    });
                }
            }

        }).start();
    }

    /**
     * 全开
     */
    public void openAllCmd(final String serverIp, final int serverPort, final ISendMessageListener listener) {
        new Thread(){
            @Override
            public void run() {
                try {
                    setServerIp(serverIp, serverPort);
//                    Socket socketTcp = new Socket(serverIp, serverPort);
//                    socketTcp.setKeepAlive(false);
//                    SocketUtil util = new SocketUtil(socketTcp);

                    boolean sendOpenCmd1 = sendMsg(socketUtil, Consts.OPEN_CMD_1, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd2 = sendMsg(socketUtil, Consts.OPEN_CMD_2, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd3 = sendMsg(socketUtil, Consts.OPEN_CMD_3, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd4 = sendMsg(socketUtil, Consts.OPEN_CMD_4, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd5 = sendMsg(socketUtil, Consts.OPEN_CMD_5, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd6 = sendMsg(socketUtil, Consts.OPEN_CMD_6, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd7 = sendMsg(socketUtil, Consts.OPEN_CMD_7, listener);
                    Thread.sleep(1000);
                    boolean sendOpenCmd8 = sendMsg(socketUtil, Consts.OPEN_CMD_8, listener);

                    Thread.sleep(3000);
                    boolean sendOpenCmd9 = sendMsg(socketUtil, Consts.OPEN_CMD_9, listener);
                    Thread.sleep(3000);
                    boolean sendOpenCmd10 = sendMsg(socketUtil, Consts.OPEN_CMD_10, listener);
                    Thread.sleep(3000);
                    boolean sendOpenCmd11 = sendMsg(socketUtil, Consts.OPEN_CMD_11, listener);
                    Thread.sleep(3000);
                    boolean sendOpenCmd12 = sendMsg(socketUtil, Consts.OPEN_CMD_12, listener);

                    if(sendOpenCmd1 && sendOpenCmd2 && sendOpenCmd3 && sendOpenCmd4 && sendOpenCmd5 && sendOpenCmd6
                            && sendOpenCmd7 && sendOpenCmd8 && sendOpenCmd9 && sendOpenCmd10 && sendOpenCmd11 && sendOpenCmd12) {
                        if(listener != null) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    listener.sendComplete(true, "所有开启命令发送成功");
                                }
                            });
                        }
                    }else {
                        if(listener != null) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    listener.sendComplete(false, "有的命令发送失败啦");
                                }
                            });
                        }
                    }
                    socketUtil.closeConnect();
                } catch (final Exception e) {
                    if(listener != null) {
                        runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.sendComplete(false, "发送失败：" + e.getMessage());
                            }
                        });
                    }
                    e.printStackTrace();
                }
            }
        }.start();
    }

    /**
     * 全关
     */
    public void closeAllCmd(final String serverIp, final int serverPort, final ISendMessageListener listener) {
        new Thread(){
            @Override
            public void run() {
                try {
                    setServerIp(serverIp, serverPort);
//                    Socket socketTcp = new Socket(serverIp, serverPort);
//                    socketTcp.setKeepAlive(false);
//
//                    SocketUtil util = new SocketUtil(socketTcp);

                    boolean sendCloseCmd1 = sendMsg(socketUtil, Consts.CLOSE_CMD_1, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd2 = sendMsg(socketUtil, Consts.CLOSE_CMD_2, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd3 = sendMsg(socketUtil, Consts.CLOSE_CMD_3, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd4 = sendMsg(socketUtil, Consts.CLOSE_CMD_4, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd5 = sendMsg(socketUtil, Consts.CLOSE_CMD_5, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd6 = sendMsg(socketUtil, Consts.CLOSE_CMD_6, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd7 = sendMsg(socketUtil, Consts.CLOSE_CMD_7, listener);
                    Thread.sleep(1000);
                    boolean sendCloseCmd8 = sendMsg(socketUtil, Consts.CLOSE_CMD_8, listener);

                    Thread.sleep(3000);
                    boolean sendCloseCmd9 = sendMsg(socketUtil, Consts.CLOSE_CMD_9, listener);
                    Thread.sleep(3000);
                    boolean sendCloseCmd10 = sendMsg(socketUtil, Consts.CLOSE_CMD_10, listener);
                    Thread.sleep(3000);
                    boolean sendCloseCmd11 = sendMsg(socketUtil, Consts.CLOSE_CMD_11, listener);
                    Thread.sleep(3000);
                    boolean sendCloseCmd12 = sendMsg(socketUtil, Consts.CLOSE_CMD_12, listener);

                    if(sendCloseCmd1 && sendCloseCmd2 && sendCloseCmd3 && sendCloseCmd4 && sendCloseCmd5 && sendCloseCmd6
                            && sendCloseCmd7 && sendCloseCmd8 && sendCloseCmd9 && sendCloseCmd10 && sendCloseCmd11 && sendCloseCmd12) {
                        if(listener != null) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    listener.sendComplete(true, "全关命令发送成功");
                                }
                            });
                        }
                    }else {
                        if(listener != null) {
                            runOnUIThread(new Runnable() {
                                @Override
                                public void run() {
                                    listener.sendComplete(false, "全关发送失败啦");
                                }
                            });
                        }
                    }
                    socketUtil.closeConnect();
                } catch (final Exception e) {
                    if(listener != null) {
                        runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.sendComplete(false, "发送失败：" + e.getMessage());
                            }
                        });
                    }
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void onSendFail(ISendMessageListener listener) {
        if(listener != null) {
            listener.sendComplete(false, "发送失败");
        }
    }

    /**
     * 发送单个命令
     * @param data
     * @return
     */
    private boolean sendMsg(final SocketUtil socketUtil, final String data, final ISendMessageListener listener) {
        try {
            socketUtil.sendData(data);
            if(listener != null) {
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        listener.sendProgress(true, data, "发送成功");
                    }
                });
            }
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            if(listener != null) {
                runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        listener.sendProgress(false, data, "发送时发生异常：" + e.getMessage());
                    }
                });
            }
            return false;
        }
    }

    /**
     * 发送测试消息
     * @param serverIp
     * @param serverPort
     * @param data
     * @param listener
     */
    public void sendMsg(final String serverIp, final int serverPort, final String data, final ISendMessageListener listener) {
        new Thread(){
            @Override
            public void run() {
                Socket socketTcp = null;
                try {
                    setServerIp(serverIp, serverPort);
//                    socketTcp = new Socket(serverIp, serverPort);
//                    SocketUtil util = new SocketUtil(socketTcp);
                    sendMsg(socketUtil, data, listener);
                    socketUtil.closeConnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    /**
     * 获取TCP连接
     *
     * @param serverIp ：服务Ip地址
     * @param prot     ：端口号
     * @param data     ：data 要发送的数据
     * @param call     ：CallBackSocket  接口
     */
    public void getTCPConnect(String serverIp, int prot, String data, CallBackSocketTCP call) {
        try {
            socketTcp = new Socket(serverIp, prot);
            SocketUtil util = new SocketUtil(socketTcp);
            util.sendData(data);

            boolean ba = util.isConnect();
            //把值给接口，这里的接口作用，就是传值的作用
            call.isConnect(ba);
            LogUtil.thduan("当前Soket是否连接：" + ba);
            String info = util.receiveData();
            //同理
            call.Receive(info);
            LogUtil.thduan(" 服务器说：" + info);
//            util.closeConnect();    //每次发送完之后关闭socket
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            //FIXME， 发生异常、或错误信息时，在界面上打印出来
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * UDP连接，
     *
     * @param port 端口号
     */
    public void getUDPConnect(int port, String datas, CallBackSocketUDP call) {
        try {
               /*
                 * 向服务器端发送数据
                 */
            // 1.定义服务器的地址、端口号、数据localhost
//            InetAddress address = InetAddress.getByName("localhost");

            InetAddress address = InetAddress.getByName(Consts.DEF_SERVER_IP);

//                port = 8800;
            byte[] data = datas.getBytes();
            // 2.创建数据报，包含发送的数据信息
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            // 3.创建DatagramSocket对象
            socketUdp = new DatagramSocket();
            // 4.向服务器端发送数据报
            socketUdp.send(packet);


            LogUtil.thduan("udp 发送完：" + datas);

//            boolean b = true;
//            while (b) {
//                         /*
//                         * 接收服务器端响应的数据
//                         */
//                // 1.创建数据报，用于接收服务器端响应的数据
//                byte[] data2 = new byte[1024];
//                DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
//                // 2.接收服务器响应的数据
//                socketUdp.receive(packet2);
//                // 3.读取数据
//                String reply = new String(data2, 0, packet2.getLength());
//
//                call.Receive(reply);//把发送的数据交给接口
//
//                LogUtil.thduan("我是客户端，服务器说：" + reply);
//                // 4.关闭资源
//            }
//              socketUdp.close();

        } catch (Exception e) {
            LogUtil.thduan("udp 发送异常：" + e.getMessage());
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 关闭 这里请教一个问题。 就是我关闭不了。为了实现长连接。怎么弄。
     */
    public void closeSocket() {
        if (socketUdp != null) {
            socketUdp.close();
            LogUtil.thduan("关闭了UDP连接");
        } else if (socketTcp != null) {
            try {
                socketTcp.close();
                LogUtil.thduan("关闭了TCP连接");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            LogUtil.thduan("没有打开无须关闭！！");
        }
    }

    private void runOnUIThread(Runnable runnable) {
        new android.os.Handler(Looper.getMainLooper()).post(runnable);
    }

}